<?php

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Capsule\Manager as DB;
use Illuminate\Database\Eloquent\SoftDeletes;

class orderModel extends Model
{
    use SoftDeletes;
    use \app\traits\orderoperation, \app\traits\orderstatus, \app\traits\orderscope;

    // 订单状态
    const STATUS_INVALID = -2;
    const STATUS_CANCEL = -1;
    const STATUS_NOPAY = 0;
    const STATUS_PAYED = 1;
    const STATUS_FINISH = 2;

	protected $table 		= 'order';
	protected $primaryKey	= 'id';

	protected $appends      = [
//        'status_code',
//        'status_name',
//        'status_desc',
//        'btns',
//        'abtns',
//        'ext_arr',
//        'createtime'
        'pay_type_text'
    ];

	/* -------------------------- 访问器 ------------------------ */

    public function getPlatformTextAttribute()
    {
        // H5=H5,wxOfficialAccount=微信公众号,wxMiniProgram=微信小程序,App=App
        switch ($this->attributes['platform']) {
            case 'H5':
            case 'App':
                return $this->attributes['platform'];
            case 'wxOfficialAccount':
                return '微信公众号';
            case 'wxMiniProgram':
                return '微信小程序';
        }
    }

    public function getPayTypeTextAttribute(){
        // wechat=微信支付,alipay=支付宝,wallet=钱包支付,score=积分支付
        switch ($this->attributes['pay_type']) {
            case 'wechat':
                return '微信支付';
            case 'alipay':
                return '支付宝';
            case 'wallet':
                return '钱包支付';
            case 'score':
                return '积分支付';
            case 'JoinPay-wx':
                return '汇聚支付-微信';
            case 'JoinPay-ali':
                return '汇聚支付-支付宝';
            case 'pickgoods':
                return '提货卡';
            case 'helibao':
                return '合利宝';
            case 'patch':
                return '手动补单';
            default:
                return '未支付';
        }
    }

    public function getCreatetimeAttribute($value)
    {
        return strtotime($this->attributes['created_at']);
    }

    public function getExtArrAttribute($value)
    {
        $ext = (isset($this->attributes['ext']) && $this->attributes['ext']) ? json_decode($this->attributes['ext'], true) : [];
        // if ($ext && isset($ext['activity_discount_infos']) && $ext['activity_discount_infos']) {
        //
        //     foreach ($ext['activity_discount_infos'] as $key => $info) {
        //         $ext['activity_discount_infos'][$key]['activity_type_text'] = Activity::getTypeList()[$info['activity_type']];
        //         $ext['activity_discount_infos'][$key]['format_text'] = Activity::formatDiscountTags($info['activity_type'], array_merge([
        //             'type' => $info['rule_type'],
        //         ], $info['discount_rule']));
        //     }
        // }
        return $ext;
    }

    protected function getStatus($type)
    {
        $btns = [];
        $abtns = [];
        $status_name = '';
        $status_desc = '';

        switch ($this->status_code) {
            case 'cancel':
                $status_name = '已取消';
                $status_desc = '订单已取消';
                $btns[] = 'delete';     // 删除订单
                break;
            case 'invalid':
                $status_name = '交易关闭';
                $status_desc = '交易关闭';
                $btns[] = 'delete';     // 删除订单
                break;
            case 'nopay':
                $status_name = '待付款';
                $status_desc = '等待买家付款';
                $btns[] = 'cancel';     // 取消订单
                $btns[] = 'pay';        // 支付
                break;

            // 已支付的
            case 'commented':
                $status_name = '已评价';
                $status_desc = '订单已评价';

                $dispatchType = $this->getItemDispatchType($this->item);
                if (in_array('express', $dispatchType)) {
                    $btns[] = 'express';        // 查看物流
                }
                $abtns[] = 'refund';        // 全部退款  直接不申请退款
                break;
            case 'nocomment':
                $status_name = '待评价';
                $status_desc = '等待买家评价';

                $dispatchType = $this->getItemDispatchType($this->item);
                if (in_array('express', $dispatchType)) {
                    $btns[] = 'express';        // 查看物流
                }
                $abtns[] = 'refund';        // 全部退款  直接不申请退款
                break;
            case 'noget':
                $dispatchType = $this->getItemDispatchType($this->item);

                $status_name = '待收货';
                $status_desc = '等待买家收货';
                if (in_array('express', $dispatchType)) {
                    $btns[] = 'express';        // 查看物流
                    $btns[] = 'get';
                } else {
                    if (count($dispatchType) == 1) {
                        // item 只有一种发货方式
                        $dispatch_type = $dispatchType[0] ?? '';

                        switch($dispatch_type) {
                            case 'selfetch':
                                $status_name = '待提货/到店';
                                $status_desc = '等待买家提货/到店';
                                break;
                            case 'store':
                                $status_name = '待取货';
                                $status_desc = '卖家上门配送中';
                                break;
                        }
                    }
                }
                $abtns[] = 'refund';        // 全部退款  直接不申请退款
                break;
            case 'nosend':
                $is_send_btn = false;
                $is_send_store_btn = false;
                foreach ($this->item as $key => $item) {
                    // 获取 item status
                    $dispatchType[] = $item['dispatch_type'];

                    // 如果有一个快递的未发货，显示发货按钮
                    if ($item['dispatch_type'] == 'express' && $item['dispatch_status'] == orderitemModel::DISPATCH_STATUS_NOSEND) {
                        $is_send_btn = true;
                    }

                    // 如果有一个到店，或者商家配送未发货，显示备货按钮
                    if (in_array($item['dispatch_type'], ['store', 'selfetch']) && $item['dispatch_status'] == orderitemModel::DISPATCH_STATUS_NOSEND) {
                        $is_send_store_btn = true;
                    }
                }
                if ($is_send_btn) {
                    $abtns[] = 'send';              // 快递发货
                }
                if ($is_send_store_btn) {
                    $abtns[] = 'send_store';       // 总后台也可直接帮门店发货
                }
                $abtns[] = 'refund';        // 全部退款  直接不申请退款

                $dispatchType = $this->getItemDispatchType($this->item);
                $status_name = '待发货';
                $status_desc = '等待卖家发货';
                if (in_array('store', $dispatchType)) {
                    $status_name = '待配送';
                    $status_desc = '等待卖家上门配送';
                } else if (in_array('selfetch', $dispatchType)) {
                    $status_name = '待备货';
                    $status_desc = '等待卖家备货';
                }
                break;
            case 'refund_finish':
                $status_name = '退款完成';
                $status_desc = '订单退款完成';

                break;
            case 'refund_ing':
                $status_name = '退款处理中';
                $status_desc = '退款处理中';

                break;
            case 'groupon_ing':
                $status_name = '等待成团';
                $status_desc = '等待拼团成功';
                $abtns[] = 'refund';        // 全部退款  直接不申请退款
                break;
            case 'groupon_invalid':
                $status_name = '拼团失败';
                $status_desc = '拼团失败';

                break;
            // 已支付的结束

            case 'finish':
                $status_name = '交易完成';
                $status_desc = '交易完成';
                $btns[] = 'delete';     // 删除订单
                break;
        }

        // $ext_arr = json_decode($this->attributes['ext'], true);
        // // 是拼团订单
        // if (
        //     strpos($this->attributes['activity_type'], 'groupon') !== false &&
        //     isset($ext_arr['groupon_id']) && $ext_arr['groupon_id']
        // ) {
        //     $btns[] = 'groupon';    // 拼团详情
        // }

        return $type == 'status_name' ? $status_name : ($type == 'btns' ? $btns : ($type == 'abtns' ? $abtns : $status_desc));
    }

    // 订单列表
    public static function getList($params)
    {
        $user = \app\service\auth::getUser();
        $order = (new self())::with(['item']);
        if (!empty($params['dianpu_id'])) {
            $order = $order->where('dianpu_id', $params['dianpu_id']);
        } else {
            $order = $order->whereRaw('(member_id=? OR customer_id=?)', [$user->id, $user->id]);
        }
        switch ($params['type']) {
            case 'nopay':
                $order = $order->nopay();
                break;
            case 'nosend':
                $order = $order->payed()->nosend();
                break;
            case 'noget':
                $order = $order->payed()->noget();
                break;
            case 'nocomment':
                $order = $order->payed()->nocomment();
                break;
            case 'aftersale':
                $order = $order->payed()->aftersale();
                break;
            default:
                break;
        }

        $page = $params['page'] ?? 1;
        $per_page = $params['per_page'] ?? 10;
        $offset = ($page - 1) * $per_page;
        $total = $order->count();
        $orders = $order->orderBy('id', 'desc')->offset($offset)->limit($per_page)->get();
        $orders->each->append('status_code');
        $orders->each->append('status_name');
        $orders->each->append('status_desc');
        $orders->each->append('btns');
        $orders->each->append('ext_arr');

        // 处理未支付订单 item status_code
        $orders = $orders->toArray();
        if ($orders) {
            foreach ($orders as $key => $od) {
                $orders[$key] = self::setOrderItemStatusByOrder($od);
            }
        }

        $result = [
            'current_page' => $page,
            'last_page' => ceil($total / $per_page),
            'per_page' => $per_page,
            'total' => $total,
            'data' => $orders,
        ];

        return $result;
    }

    // 订单详情
    public static function detail($params)
    {
        $user = \app\service\auth::getUser();

        $order = (new self())
            ->with('item');
            // ->whereRaw('(member_id=? OR customer_id=?)', [$user->id, $user->id]);
        if (!empty($params['order_sn'])) {
            $order->where('order_sn', $params['order_sn']);
        }
        if (!empty($params['id'])) {
            $order->where('id', $params['id']);
        }

        $order = $order->first();
        $order->append('status_code');
        $order->append('status_name');
        $order->append('status_desc');
        $order->append('btns');
        $order->append('ext_arr');

        if (!$order) {
            throw new Exception('订单不存在');
        }

        // 处理未支付订单 item status_code
        $order = self::setOrderItemStatusByOrder($order);

        return $order;
    }

    // 订单商品详情
    public static function itemDetail($params)
    {
        $user = \app\service\auth::getUser();
        extract($params);
        $type = $params['type'] ?? 'default';

        $order = (new self())->with(['item' => function ($query) use ($order_item_id) {
            $query->where('id', $order_item_id);
        }])->where('member_id', $user->id);

        if (!empty($params['order_sn'])) {
            $order->where('order_sn', $params['order_sn']);
        }
        if (!empty($params['id'])) {
            $order->where('id', $params['id']);
        }

        $order = $order->first();

        if (!$order || !$order->item) {
            throw new Exception('订单不存在');
        }

        // 处理未支付订单 item status_code
        $order = self::setOrderItemStatusByOrder($order);
        $item = $order['item'][0];
        unset($order['item']);  // 移除订单表中的 item
        $item['order'] = $order;        // 订单信息

        if ($type == 'dispatch') {
            $store = null;
            $verifies = [];
            if (in_array($item['dispatch_type'], ['selfetch', 'store']) && $item['store_id']) {
                // 自提，商家配送

                if ($item['dispatch_type'] == 'selfetch'
                    && $item['dispatch_status'] == orderitemModel::DISPATCH_STATUS_SENDED
                    && $item['refund_status'] <= 0) {
                    // 关联核销码 TODO
                    // $verifies = Verify::where('order_id', $item['order_id'])
                    //     ->where('order_item_id', $item['id'])->select();
                }

                // $store = Store::where('id', $item['store_id'])->find();
            }
            $item['store'] = $store;        // 门店信息
            $item['verify'] = $verifies;    // 核销券列表

            // $item['autosend']
            // 订单详情，自动发货内容 待补充
        }

        return $item;
    }

    private function getItemDispatchType($item = []) {
        $dispatchType = [];
        foreach ($this->item as $key => $item) {
            // 获取 item status
            $dispatchType[] = $item['dispatch_type'];
        }
        $dispatchType = array_unique(array_filter($dispatchType));  // 过滤重复，过滤空值

        return $dispatchType;
    }

	public function item()
    {
        return $this->hasMany(orderitemModel::class, 'order_id', 'id');
    }

    public function setExt($order, $field, $origin = [])
    {
        $newExt = array_merge($origin, $field);
        $orderExt = $order['ext_arr'];
        return array_merge($orderExt, $newExt);
    }

    public function member()
    {
        return $this->belongsTo(memberModel::class, 'member_id')->select('id', 'avatar', 'nickname', 'level', 'phone');
    }

    public function customer()
    {
        return $this->belongsTo(memberModel::class, 'customer_id')->select('id', 'avatar', 'nickname', 'level', 'phone');
    }

    protected function serializeDate($date)
    {
        return $date->format('Y-m-d H:i:s');
    }

    // 支付成功回调处理
    public static function notifyProcess($type, $params){
        try{
            DB::beginTransaction();
            $params['pay_type'] = (strtoupper($type)=='ALI') ? 'alipay' : 'wechat';
            $order = (new self)->where('order_sn', $params['out_trade_no'])->lockForUpdate()->first();
            trace('orderModel:notifyProcess ' . json_encode($order), 'pay');
            if (!$order) {
                throw new Exception('order not fund');
            }
            if (bccomp($order['pay_fee'] * 100, $params['total_fee']) !== 0) {
                throw new Exception('order pay fee not right');
            }
            if ($order->status > 0) {
                throw new Exception('order has paid', 20002);
            }

            $order->paymentProcess($order, $params);
            DB::commit();
            return true;
        }catch (\Exception $e){
            DB::rollBack();
            Log::out($e->getMessage(), 'pay');
            if ($e->getCode()==20002) {
                return true;
            }
            return false;
        }
    }

    private static function notifyBody($paid_type, $order_no, $amount, $trade_no){
        $orders = DB::table('orders')->where('order_no', '=', $order_no)->first();
        if (empty($orders)){return FALSE;}
        if (bccomp($orders['amount']*100, $amount)!==0){return FALSE;}
        if ($orders['status'] > 100) {return TRUE;}
        try {
            DB::beginTransaction();
            /***1.更新order表***/
            $rows = array(
                'status'		=>	200,
                'paid_type'		=>	$paid_type,
                'paid_at'		=>	date('Y-m-d H:i:s'),
                'transactionno'	=>	$trade_no,
            );
            DB::table('orders')->where('order_no', '=', $order_no)->update($rows);
            /***2.更新库存***/
            self::updateStock($order_no);
            /***3.添加资金记录日志***/
            $rows = array(
                'members_id' => $orders['members_id'],
                'order_no' => $order_no,
                'type'=> 1,
                'fee' => $orders['amount'],
                'status' => 1,
                'remark' => '订单支付完成.',
                'created_at' => date('Y-m-d H:i:s'),
            );
            DB::table('orders_log')->insert($rows);
            DB::commit();
            return TRUE;
        } catch (Exception $e) {
            DB::rollBack();
            return FALSE;
        }
    }

    public function dianpu()
    {
        return $this->belongsTo(dianpuModel::class, 'dianpu_id', 'id');
    }

}